/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "主窗口.h"

#include <文件/file_文件名数据.h>
#include <几何图形/图形相交.h>
#include <TEST/UI_test.h>
//#include <几何图形/几何模型生成.h>

#include "A_引擎/引擎.h"
#include "A_引擎/文件工程/工程文件.h"
#include "A_引擎/文件工程/配置.h"

#include "B_场景管理/操作记录.h"

#include "框架/屏幕.h"
#include "框架/ui组件构建结构.h"
#include "框架/视口元素.h"
#include "框架/设置部件窗口.h"
#include "框架/操作环境管理.h"

#include "框架/工作区/节点视口/ui节点创建菜单.h"
#include "框架/工作区/视频图像视口/视频视口.h"
#include "框架/工作区/时间轴视口/轴视口工作区.h"

#include "渲染/渲染.h"



 
#include <随机数.h>


S_Window* window = 0;
S_Window* window_temp = 0;

static C_Widget* gui节点视口工作区 = 0;
static C_Widget* ui_实验组件 = 0;



void f_实验组件更新() {
	//f_ui_set行文本框文本(ui_实验组件, f_浮点数值转宽字符串(window->m_帧数));
}


static E_事件是否传递 on_保存工程(C_Widget* self, uint8 状态) {
	if (f_projectFile_保存当前文件() == false) {
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_写入, on_projectFile_文件打开保存, "I:/TEMP/", ".np");
	}

	f_projectFile_设置文件保存状态(true);
	return E_事件是否传递::e_事件传递_终止;
}


static E_事件是否传递 on_打开工程(C_Widget* self, uint8 状态) {
	if (f_projectFile_保存当前文件() == false) {
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_读取, on_projectFile_文件打开保存, "I:/TEMP/", ".np");
	}
	return E_事件是否传递::e_事件传递_终止;
}




static void on_GPU参数修改更新渲染器(struct S_板载缓存* buf) {
	f_render_刷新渲染(f_NodeCtx_get默认场景());
}



void f_init主窗口() {
	S_UI主题::ui_默认字体 = "雅黑";
	S_引擎配置::f_初始化着色器文件路径();
	S_节点数据::g_编译器路径 = (S_引擎配置::g_程序路径) + "compiled/";
	
	std::cout<<"create window"<<std::endl;
	window = S_框架::f_创建窗口到列队({ 1024, 576 });

	std::cout << "create render ctx" << std::endl;
	S_框架::g_3D视口环境 = f_创建渲染环境(S_框架::ctx, E_纹理格式::e_tf_RGBA8U_U, E_纹理格式::e_tf_D32F, E_MS次数::e_MS_2, { 0,1,0,1 });
	S_框架::engine.f_初始化设备数据(*S_框架::g_3D视口环境, true);


	if (S_框架::g_3D视口环境->m_支持光追) {
		
	}
	std::cout << "open ray" << std::endl;
	f_scene_开启光追(S_框架::g_Scene, *S_框架::g_3D视口环境);
	
	

	S_全局缓存::m_I32动态属性->m_Update = on_GPU参数修改更新渲染器;
	S_全局缓存::m_F32动态属性->m_Update = on_GPU参数修改更新渲染器;
	S_全局缓存::m_Vec2动态属性->m_Update = on_GPU参数修改更新渲染器;
	S_全局缓存::m_Vec3动态属性->m_Update = on_GPU参数修改更新渲染器;
	S_全局缓存::m_全局绑定参数指针->m_Update = on_GPU参数修改更新渲染器;
	//S_框架::g_Scene->m_光追后端->m_I32动态属性->m_Update = on_GPU参数修改更新渲染器;
	//S_框架::g_Scene->m_光追后端->m_F32动态属性->m_Update = on_GPU参数修改更新渲染器;
	//S_框架::g_Scene->m_光追后端->m_Vec2动态属性->m_Update = on_GPU参数修改更新渲染器;
	//S_框架::g_Scene->m_光追后端->m_Vec3动态属性->m_Update = on_GPU参数修改更新渲染器;
	//S_框架::g_Scene->m_光追后端->m_全局绑定参数指针->m_Update = on_GPU参数修改更新渲染器;

	
	std::cout << "init UI" << std::endl;
	auto ui_root = f_创建根部件({ 0.2, 0.2 }, { 0.8, 0.8 }, E_布局方式::e_VBOX布局);
	window->f_安装UI(ui_root);
	S_框架::g_UIGM = window->m_窗口GM;

	S_框架::g_界面构建   = new S_组件构建();
	S_框架::g_ui顶层画布 = f_ui_创建全屏画布(*window->m_UIctx, S_框架::g_UIGM);


	f_屏幕_初始化工作区(ui_root, *window->m_UIctx);
	f_属性栏_初始化(*window->m_UIctx);



	std::string 资源加载路径;
#ifdef 预定义_最终输出
	资源加载路径 = (S_引擎配置::g_程序路径);

	S_框架::m_库默认路径 = (S_引擎配置::g_程序路径) + "节点库/";

#else
	资源加载路径 = "D:/U/DEV/";
#endif // 预定义_最终输出
	
	
	std::cout << "load ico" << std::endl;
	//std::cout<<"资源加载路径:"<< 资源加载路径<<std::endl;
	f_ui添加图标组(S_框架::g_UIGM, {
		{S_节点UI主题::ui_节点图标, 资源加载路径 + "图标资源/节点"},
	});

	f_ui添加图标组(S_框架::g_UIGM, {
		{"默认图标", 资源加载路径 + "图标资源/文件菜单"},
		}
	);

	S_UI主题::ui_默认图标 = "默认图标";
	
	


	f_global_set全局物体显示();

	//f_ob_initGPU变换矩阵(*S_框架::g_3D视口环境);
	f_初始化3D视口基准网格线(*S_框架::g_3D视口环境);
	f_初始化变换手柄(*S_框架::g_3D视口环境);

	
	S_框架::g_UIGM->mf_输入执行前回调 = f_屏幕_开始更新工作区;
	S_框架::g_UIGM->mf_输入执行后回调 = f_屏幕_更新工作区;
	
	//============================= 数据初始化 ============================
	S_框架::f_初始化预设资源(*S_框架::g_3D视口环境);

	f_projectFile_设置工程目录("");



	//f_test_ArrayInsert();
	//f_test_GPU缓存块操作(window->m_UIctx->m_Ctx);
	//auto w = f_test_构建菜单项组件(*window->m_UIctx);
	//f_test_VG变换内存(*window->m_UIctx);
	//auto w = f_test_Vec3组件(*window->m_UIctx);
	//auto w = f_test_菜单组件(*window->m_UIctx);
	//auto* w = f_test_行文本编辑框组件(*window->m_UIctx);
	//auto* w = f_test_构建3D视口组件(*window->m_UIctx, *S_框架::g_3D视口环境);
	//auto* w = f_test_构建菜单项组件(*window->m_UIctx);
	//auto* w = f_test_构建枚举组件(*window->m_UIctx);
	//auto* w = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_时间轴);
	//ui_root->f_添加子组件(w);
	//return;

	std::cout << "load ico" << std::endl;

	auto* ui_视频视口 = f_图像View_创建视频窗口(*window->m_UIctx);
	ui_视频视口->m_WName = L"视频图像";
	f_图像View_设置当前视频视口(ui_视频视口);
	
	{
		auto ui主菜单 = f_界面构建_主菜单创建(*window->m_UIctx);
		ui_root->f_添加子组件(ui主菜单);
	}


	{
		auto* 屏幕左上 = f_屏幕_创建工作区(*window->m_UIctx);
		auto* 屏幕左下 = f_屏幕_创建工作区(*window->m_UIctx);
		auto* 屏幕右 = f_屏幕_创建工作区(*window->m_UIctx);
		

		auto* ui工作区_场景视口 = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_3D视口);
		auto* ui工作区_节点视口 = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_节点视口);
		auto* ui工作区_时间视口 = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_时间轴);
		auto* ui工作区_文本视口 = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_文本编辑视口);
		auto* ui工作区_渲染合成 = f_屏幕_create工作区页面(*window->m_UIctx, E_工作区类型::e_渲染合成视口);
		{
			f_屏幕_添加工作区页面(屏幕左上, ui工作区_场景视口);
			//f_屏幕_添加工作区页面(屏幕左上, ui工作区_文本视口);
			ui工作区_场景视口->m_是否延展 = { true, true };
			ui工作区_文本视口->m_是否延展 = { true, true };

			f_屏幕_添加工作区页面(屏幕右, ui工作区_节点视口);
			ui工作区_节点视口->m_是否延展 = { true, true };

			f_屏幕_添加工作区页面(屏幕左下, ui工作区_时间视口);
			ui工作区_时间视口->m_是否延展 = { true, true };
			f_屏幕_添加工作区页面(屏幕左下, ui工作区_渲染合成);
			ui工作区_渲染合成->m_是否延展 = { true, true };
		}
		ui工作区_场景视口->m_WName = L"ui工作区_场景视口";
		ui工作区_节点视口->m_WName = L"ui工作区_节点视口";
		ui工作区_时间视口->m_WName = L"ui工作区_时间视口";
		ui工作区_文本视口->m_WName = L"ui工作区_文本视口";


		auto* ui编辑工作区 = f_ui_创建分割窗口({ 屏幕左上 , 屏幕左下 }, E_方向::e_横向, { 0.8f, 1.0f }, *window->m_UIctx);
		屏幕左上->m_是否延展 = { true, true };
		屏幕左下->m_是否延展 = { true, true };

		{
			auto* ui工作区 = f_ui_创建分割窗口({ ui编辑工作区 , 屏幕右 }, E_方向::e_纵向, { 0.6f, 1.0f }, *window->m_UIctx);
			//auto* ui工作区 = f_ui_创建分割窗口({ ui编辑工作区 }, E_方向::e_纵向, { 0.6f, 1.0f }, *window->m_UIctx);
			//auto* ui工作区 = f_ui_创建分割窗口({ 屏幕右 }, E_方向::e_纵向, { 0.6f, 1.0f }, *window->m_UIctx);
			ui工作区->m_是否延展 = { true, true };
			
			ui_root->f_添加子组件(ui工作区);
		}
	}
	


	
	
	std::cout << "init key" << std::endl;

	//========================== 所有对话框创建 ==============================
	S_框架::g_ui文件对话框 = f_ui_创建文件对话框(on_projectFile_文件打开保存, "I:/TEMP", *window->m_UIctx);
	S_框架::g_ui文件对话框->m_TypeName = "对话框";
	f_ui_管理器添加根部件(S_框架::g_UIGM, S_框架::g_ui文件对话框);
	


	//============= 注册快捷键 =================
	S_键盘键位映射* 全局快捷键 = f_widget_init_键盘位映射();
	
	全局快捷键->event = f_操作记录_全局撤销;
	全局快捷键->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	全局快捷键->键盘按键[3] = S_InputKey::e_KEY_Z;
	全局快捷键->键盘状态[0] = DEF_按键状态_按下中;
	全局快捷键->键盘状态[3] = DEF_按键状态_放开;
	C_键位映射配置::f_添加全局操作键位((S_键位映射*)全局快捷键, L"撤销操作");
	f_ui_注册全局快捷键(*全局快捷键);
	//f_ui_注册全局快捷键(Keys, f_操作记录_全局撤销);
	//Keys.clear();

	全局快捷键 = f_widget_init_键盘位映射();
	全局快捷键->event = f_操作记录_全局重做;
	全局快捷键->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	全局快捷键->键盘按键[1] = S_InputKey::e_KEY_左SHIFT;
	全局快捷键->键盘按键[3] = S_InputKey::e_KEY_Z;
	全局快捷键->键盘状态[0] = DEF_按键状态_按下中;
	全局快捷键->键盘状态[1] = DEF_按键状态_按下中;
	全局快捷键->键盘状态[3] = DEF_按键状态_放开;
	C_键位映射配置::f_添加全局操作键位((S_键位映射*)全局快捷键, L"重做操作");
	f_ui_注册全局快捷键(*全局快捷键);
	//f_ui_注册全局快捷键(Keys, f_操作记录_全局重做);
	//Keys.clear();

	全局快捷键 = f_widget_init_键盘位映射();
	全局快捷键->event = on_保存工程;
	全局快捷键->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	全局快捷键->键盘按键[3] = S_InputKey::e_KEY_S;
	全局快捷键->键盘状态[0] = DEF_按键状态_按下中;
	全局快捷键->键盘状态[3] = DEF_按键状态_按下;
	C_键位映射配置::f_添加全局操作键位((S_键位映射*)全局快捷键, L"保存文件");
	f_ui_注册全局快捷键(*全局快捷键);
	//f_ui_注册全局快捷键(Keys, on_保存工程);
	//Keys.clear();

	全局快捷键 = f_widget_init_键盘位映射();
	全局快捷键->event = on_打开工程;
	全局快捷键->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	全局快捷键->键盘按键[3] = S_InputKey::e_KEY_O;
	全局快捷键->键盘状态[0] = DEF_按键状态_按下中;
	全局快捷键->键盘状态[3] = DEF_按键状态_按下;
	C_键位映射配置::f_添加全局操作键位((S_键位映射*)全局快捷键, L"打开文件");
	f_ui_注册全局快捷键(*全局快捷键);


	
	//快捷键.event = on_保存工程;
	//for (uint8 i = 0; i < 4; ++i) {
	//	快捷键.键盘按键[i] = 0;
	//	快捷键.键盘状态[i] = 0;
	//}
	//快捷键.键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	//快捷键.键盘按键[3] = S_InputKey::e_KEY_D;
	//快捷键.键盘状态[0] = DEF_按键状态_按下中;
	//快捷键.键盘状态[3] = DEF_按键状态_按下中;
	//f_ui_注册全局快捷键(快捷键);


	S_鼠标键位映射* 全局鼠标键位 = f_widget_init_鼠标键位映射();
	全局鼠标键位->event = f_工作区_时间帧步进;
	全局鼠标键位->键盘按键[0] = S_InputKey::e_KEY_左ALT;
	全局鼠标键位->键盘状态[0] = DEF_按键状态_按下中;
	全局鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	全局鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	C_键位映射配置::f_添加全局操作键位((S_键位映射*)全局鼠标键位, L"步进时间帧");
	f_ui_注册全局鼠标快捷键(*全局鼠标键位);

	/*window_temp = f_创建窗口("mbt", S_Core::ctx, { 0,0, 640, 420 });
	window_temp->m_采样 = E_MS次数::e_MS_4;
	window_temp->f_创建绘制面(S_Core::engine.m_绘图框架, S_Core::ctx, { 640, 420 });
	window_temp->f_安装UI(f_创建设置窗口根组件(*window_temp->m_UI环境));*/


}

#include <omp.h>
void f_run主循环() {
	f_projectFile_设置文件保存状态(false);
	//f_实验组件更新();
	
	//auto a = f_Range<uint32>(0, 512);
	//f_随机打乱(a, 512);

	
	//f_node_开始运行节点树();

	//std::atomic_flag a;
	//volatile int32 m_分配内存锁 = 1;
	//int32 计算 = 0;
	//#pragma omp parallel for
	//for (int32 i = 0; i < 100000; ++i) {
	//	while (1) {
	//		if (a.test_and_set() == false) {
	//			++计算;
	//			a.clear();
	//			break;
	//		}
	//	}
	//}
	//std::cout << "m_分配内存等待 计算:" << 计算 << std::endl;
	std::cout << "loop" << std::endl;

	bool quit = true;
	while (quit) {
		quit = false;
		for (auto& w : S_框架::g_主窗口) {
			quit |= w->f_轮询窗口事件();
		}
	}

	f_属性栏_清理();


	f_render_关闭渲染器();
	f_ui_销毁全屏画布(S_框架::g_ui顶层画布);

	
	f_ui_释放图标组(S_框架::g_UIGM);
	f_ui_释放字体(S_框架::g_UIGM);

}

void f_close主窗口() {
	
}




/*bool on_文件打开保存(C_Widget* self, const std::vector<std::string>& filenames, E_对话框类型 方式) {
	switch (方式)
	{
	case E_对话框类型::e_读取:
		for (auto& path : filenames) {
			f_projectFile_设置工程目录(path);
			//path = "I:/TEMP/n2.ms";
			FILE* f = fopen(path.c_str(), "rb");
			if (f) {
				auto 扩展名 = f_file_文件扩展名(path);

				if (扩展名 == ".np") {
					f_projectFile_载入(f);
					f_NodeView_安装节点树后端(f_node_get节点树(0));
				}
				else if (扩展名 == ".ms") {
					auto objs = f_load多物体(f, *S_框架::g_3D视口环境);
					auto* 材质 = new S_单色面材质(*S_框架::g_3D视口环境);
					for (auto& ob : objs) {
						f_ob_set材质(ob, 材质);
						S_框架::g_Scene->f_add物体(ob);
					}
				}
				else if (扩展名 == ".ncp") {
				}
				fclose(f);
			}
			else {
				std::cout << "打开文件失败" << std::endl;
			}
		}
		break;
	case E_对话框类型::e_写入:
		for (auto& path : filenames) {
			FILE* f = fopen(path.c_str(), "wb");
			if (f) {
				auto 扩展名 = f_file_文件扩展名(path);

				if (扩展名 == ".np") {
					f_projectFile_保存(f);
				}
				else if (扩展名 == ".ncp") {
				}
				fclose(f);
			}
			else {
				std::cout << "保存文件失败" << std::endl;
			}
		}
		break;
	case E_对话框类型::e_关闭:
		break;
	default:
		break;
	}

	f_ui_switchRootWidget(S_框架::g_UIGM, 0);
	f_projectFile_设置文件保存状态(true);
	return true;
}*/


















